import common as CM
from sage.all import *

from aes_common import myxor, myand, allints
from aes_common import MAXKC, MAXNR, byte, is_byte, byte_index, is_block, key_index, is_key, roundkey_index
"""
based on the ADA _original_ implementation
"""


word = 2**32
is_word = lambda w: 0 <= w <= word-1


is_key_schedule = lambda ks: len(ks)==roundkey_index and CM.vall(ks,is_word)


Te0 = map(Integer,[3328402341, 4168907908, 4000806809, 4135287693, 4294111757, 3597364157, 3731845041, 2445657428, 1613770832, 33620227, 3462883241, 1445669757, 3892248089, 3050821474, 1303096294, 3967186586, 2412431941, 528646813, 2311702848, 4202528135, 4026202645, 2992200171, 2387036105, 4226871307, 1101901292, 3017069671, 1604494077, 1169141738, 597466303, 1403299063, 3832705686, 2613100635, 1974974402, 3791519004, 1033081774, 1277568618, 1815492186, 2118074177, 4126668546, 2211236943, 1748251740, 1369810420, 3521504564, 4193382664, 3799085459, 2883115123, 1647391059, 706024767, 134480908, 2512897874, 1176707941, 2646852446, 806885416, 932615841, 168101135, 798661301, 235341577, 605164086, 461406363, 3756188221, 3454790438, 1311188841, 2142417613, 3933566367, 302582043, 495158174, 1479289972, 874125870, 907746093, 3698224818, 3025820398, 1537253627, 2756858614, 1983593293, 3084310113, 2108928974, 1378429307, 3722699582, 1580150641, 327451799, 2790478837, 3117535592, 0, 3253595436, 1075847264, 3825007647, 2041688520, 3059440621, 3563743934, 2378943302, 1740553945, 1916352843, 2487896798, 2555137236, 2958579944, 2244988746, 3151024235, 3320835882, 1336584933, 3992714006, 2252555205, 2588757463, 1714631509, 293963156, 2319795663, 3925473552, 67240454, 4269768577, 2689618160, 2017213508, 631218106, 1269344483, 2723238387, 1571005438, 2151694528, 93294474, 1066570413, 563977660, 1882732616, 4059428100, 1673313503, 2008463041, 2950355573, 1109467491, 537923632, 3858759450, 4260623118, 3218264685, 2177748300, 403442708, 638784309, 3287084079, 3193921505, 899127202, 2286175436, 773265209, 2479146071, 1437050866, 4236148354, 2050833735, 3362022572, 3126681063, 840505643, 3866325909, 3227541664, 427917720, 2655997905, 2749160575, 1143087718, 1412049534, 999329963, 193497219, 2353415882, 3354324521, 1807268051, 672404540, 2816401017, 3160301282, 369822493, 2916866934, 3688947771, 1681011286, 1949973070, 336202270, 2454276571, 201721354, 1210328172, 3093060836, 2680341085, 3184776046, 1135389935, 3294782118, 965841320, 831886756, 3554993207, 4068047243, 3588745010, 2345191491, 1849112409, 3664604599, 26054028, 2983581028, 2622377682, 1235855840, 3630984372, 2891339514, 4092916743, 3488279077, 3395642799, 4101667470, 1202630377, 268961816, 1874508501, 4034427016, 1243948399, 1546530418, 941366308, 1470539505, 1941222599, 2546386513, 3421038627, 2715671932, 3899946140, 1042226977, 2521517021, 1639824860, 227249030, 260737669, 3765465232, 2084453954, 1907733956, 3429263018, 2420656344, 100860677, 4160157185, 470683154, 3261161891, 1781871967, 2924959737, 1773779408, 394692241, 2579611992, 974986535, 664706745, 3655459128, 3958962195, 731420851, 571543859, 3530123707, 2849626480, 126783113, 865375399, 765172662, 1008606754, 361203602, 3387549984, 2278477385, 2857719295, 1344809080, 2782912378, 59542671, 1503764984, 160008576, 437062935, 1707065306, 3622233649, 2218934982, 3496503480, 2185314755, 697932208, 1512910199, 504303377, 2075177163, 2824099068, 1841019862, 739644986])

Te1 = map(Integer,[2781242211, 2230877308, 2582542199, 2381740923, 234877682, 3184946027, 2984144751, 1418839493, 1348481072, 50462977, 2848876391, 2102799147, 434634494, 1656084439, 3863849899, 2599188086, 1167051466, 2636087938, 1082771913, 2281340285, 368048890, 3954334041, 3381544775, 201060592, 3963727277, 1739838676, 4250903202, 3930435503, 3206782108, 4149453988, 2531553906, 1536934080, 3262494647, 484572669, 2923271059, 1783375398, 1517041206, 1098792767, 49674231, 1334037708, 1550332980, 4098991525, 886171109, 150598129, 2481090929, 1940642008, 1398944049, 1059722517, 201851908, 1385547719, 1699095331, 1587397571, 674240536, 2704774806, 252314885, 3039795866, 151914247, 908333586, 2602270848, 1038082786, 651029483, 1766729511, 3447698098, 2682942837, 454166793, 2652734339, 1951935532, 775166490, 758520603, 3000790638, 4004797018, 4217086112, 4137964114, 1299594043, 1639438038, 3464344499, 2068982057, 1054729187, 1901997871, 2534638724, 4121318227, 1757008337, 0, 750906861, 1614815264, 535035132, 3363418545, 3988151131, 3201591914, 1183697867, 3647454910, 1265776953, 3734260298, 3566750796, 3903871064, 1250283471, 1807470800, 717615087, 3847203498, 384695291, 3313910595, 3617213773, 1432761139, 2484176261, 3481945413, 283769337, 100925954, 2180939647, 4037038160, 1148730428, 3123027871, 3813386408, 4087501137, 4267549603, 3229630528, 2315620239, 2906624658, 3156319645, 1215313976, 82966005, 3747855548, 3245848246, 1974459098, 1665278241, 807407632, 451280895, 251524083, 1841287890, 1283575245, 337120268, 891687699, 801369324, 3787349855, 2721421207, 3431482436, 959321879, 1469301956, 4065699751, 2197585534, 1199193405, 2898814052, 3887750493, 724703513, 2514908019, 2696962144, 2551808385, 3516813135, 2141445340, 1715741218, 2119445034, 2872807568, 2198571144, 3398190662, 700968686, 3547052216, 1009259540, 2041044702, 3803995742, 487983883, 1991105499, 1004265696, 1449407026, 1316239930, 504629770, 3683797321, 168560134, 1816667172, 3837287516, 1570751170, 1857934291, 4014189740, 2797888098, 2822345105, 2754712981, 936633572, 2347923833, 852879335, 1133234376, 1500395319, 3084545389, 2348912013, 1689376213, 3533459022, 3762923945, 3034082412, 4205598294, 133428468, 634383082, 2949277029, 2398386810, 3913789102, 403703816, 3580869306, 2297460856, 1867130149, 1918643758, 607656988, 4049053350, 3346248884, 1368901318, 600565992, 2090982877, 2632479860, 557719327, 3717614411, 3697393085, 2249034635, 2232388234, 2430627952, 1115438654, 3295786421, 2865522278, 3633334344, 84280067, 33027830, 303828494, 2747425121, 1600795957, 4188952407, 3496589753, 2434238086, 1486471617, 658119965, 3106381470, 953803233, 334231800, 3005978776, 857870609, 3151128937, 1890179545, 2298973838, 2805175444, 3056442267, 574365214, 2450884487, 550103529, 1233637070, 4289353045, 2018519080, 2057691103, 2399374476, 4166623649, 2148108681, 387583245, 3664101311, 836232934, 3330556482, 3100665960, 3280093505, 2955516313, 2002398509, 287182607, 3413881008, 4238890068, 3597515707, 975967766])

Te2 = map(Integer,[1671808611, 2089089148, 2006576759, 2072901243, 4061003762, 1807603307, 1873927791, 3310653893, 810573872, 16974337, 1739181671, 729634347, 4263110654, 3613570519, 2883997099, 1989864566, 3393556426, 2191335298, 3376449993, 2106063485, 4195741690, 1508618841, 1204391495, 4027317232, 2917941677, 3563566036, 2734514082, 2951366063, 2629772188, 2767672228, 1922491506, 3227229120, 3082974647, 4246528509, 2477669779, 644500518, 911895606, 1061256767, 4144166391, 3427763148, 878471220, 2784252325, 3845444069, 4043897329, 1905517169, 3631459288, 827548209, 356461077, 67897348, 3344078279, 593839651, 3277757891, 405286936, 2527147926, 84871685, 2595565466, 118033927, 305538066, 2157648768, 3795705826, 3945188843, 661212711, 2999812018, 1973414517, 152769033, 2208177539, 745822252, 439235610, 455947803, 1857215598, 1525593178, 2700827552, 1391895634, 994932283, 3596728278, 3016654259, 695947817, 3812548067, 795958831, 2224493444, 1408607827, 3513301457, 0, 3979133421, 543178784, 4229948412, 2982705585, 1542305371, 1790891114, 3410398667, 3201918910, 961245753, 1256100938, 1289001036, 1491644504, 3477767631, 3496721360, 4012557807, 2867154858, 4212583931, 1137018435, 1305975373, 861234739, 2241073541, 1171229253, 4178635257, 33948674, 2139225727, 1357946960, 1011120188, 2679776671, 2833468328, 1374921297, 2751356323, 1086357568, 2408187279, 2460827538, 2646352285, 944271416, 4110742005, 3168756668, 3066132406, 3665145818, 560153121, 271589392, 4279952895, 4077846003, 3530407890, 3444343245, 202643468, 322250259, 3962553324, 1608629855, 2543990167, 1154254916, 389623319, 3294073796, 2817676711, 2122513534, 1028094525, 1689045092, 1575467613, 422261273, 1939203699, 1621147744, 2174228865, 1339137615, 3699352540, 577127458, 712922154, 2427141008, 2290289544, 1187679302, 3995715566, 3100863416, 339486740, 3732514782, 1591917662, 186455563, 3681988059, 3762019296, 844522546, 978220090, 169743370, 1239126601, 101321734, 611076132, 1558493276, 3260915650, 3547250131, 2901361580, 1655096418, 2443721105, 2510565781, 3828863972, 2039214713, 3878868455, 3359869896, 928607799, 1840765549, 2374762893, 3580146133, 1322425422, 2850048425, 1823791212, 1459268694, 4094161908, 3928346602, 1706019429, 2056189050, 2934523822, 135794696, 3134549946, 2022240376, 628050469, 779246638, 472135708, 2800834470, 3032970164, 3327236038, 3894660072, 3715932637, 1956440180, 522272287, 1272813131, 3185336765, 2340818315, 2323976074, 1888542832, 1044544574, 3049550261, 1722469478, 1222152264, 50660867, 4127324150, 236067854, 1638122081, 895445557, 1475980887, 3117443513, 2257655686, 3243809217, 489110045, 2662934430, 3778599393, 4162055160, 2561878936, 288563729, 1773916777, 3648039385, 2391345038, 2493985684, 2612407707, 505560094, 2274497927, 3911240169, 3460925390, 1442818645, 678973480, 3749357023, 2358182796, 2717407649, 2306869641, 219617805, 3218761151, 3862026214, 1120306242, 1756942440, 1103331905, 2578459033, 762796589, 252780047, 2966125488, 1425844308, 3151392187, 372911126])

Te3 = map(Integer,[1667474886, 2088535288, 2004326894, 2071694838, 4075949567, 1802223062, 1869591006, 3318043793, 808472672, 16843522, 1734846926, 724270422, 4278065639, 3621216949, 2880169549, 1987484396, 3402253711, 2189597983, 3385409673, 2105378810, 4210693615, 1499065266, 1195886990, 4042263547, 2913856577, 3570689971, 2728590687, 2947541573, 2627518243, 2762274643, 1920112356, 3233831835, 3082273397, 4261223649, 2475929149, 640051788, 909531756, 1061110142, 4160160501, 3435941763, 875846760, 2779116625, 3857003729, 4059105529, 1903268834, 3638064043, 825316194, 353713962, 67374088, 3351728789, 589522246, 3284360861, 404236336, 2526454071, 84217610, 2593830191, 117901582, 303183396, 2155911963, 3806477791, 3958056653, 656894286, 2998062463, 1970642922, 151591698, 2206440989, 741110872, 437923380, 454765878, 1852748508, 1515908788, 2694904667, 1381168804, 993742198, 3604373943, 3014905469, 690584402, 3823320797, 791638366, 2223281939, 1398011302, 3520161977, 0, 3991743681, 538992704, 4244381667, 2981218425, 1532751286, 1785380564, 3419096717, 3200178535, 960056178, 1246420628, 1280103576, 1482221744, 3486468741, 3503319995, 4025428677, 2863326543, 4227536621, 1128514950, 1296947098, 859002214, 2240123921, 1162203018, 4193849577, 33687044, 2139062782, 1347481760, 1010582648, 2678045221, 2829640523, 1364325282, 2745433693, 1077985408, 2408548869, 2459086143, 2644360225, 943212656, 4126475505, 3166494563, 3065430391, 3671750063, 555836226, 269496352, 4294908645, 4092792573, 3537006015, 3452783745, 202118168, 320025894, 3974901699, 1600119230, 2543297077, 1145359496, 387397934, 3301201811, 2812801621, 2122220284, 1027426170, 1684319432, 1566435258, 421079858, 1936954854, 1616945344, 2172753945, 1330631070, 3705438115, 572679748, 707427924, 2425400123, 2290647819, 1179044492, 4008585671, 3099120491, 336870440, 3739122087, 1583276732, 185277718, 3688593069, 3772791771, 842159716, 976899700, 168435220, 1229577106, 101059084, 606366792, 1549591736, 3267517855, 3553849021, 2897014595, 1650632388, 2442242105, 2509612081, 3840161747, 2038008818, 3890688725, 3368567691, 926374254, 1835907034, 2374863873, 3587531953, 1313788572, 2846482505, 1819063512, 1448540844, 4109633523, 3941213647, 1701162954, 2054852340, 2930698567, 134748176, 3132806511, 2021165296, 623210314, 774795868, 471606328, 2795958615, 3031746419, 3334885783, 3907527627, 3722280097, 1953799400, 522133822, 1263263126, 3183336545, 2341176845, 2324333839, 1886425312, 1044267644, 3048588401, 1718004428, 1212733584, 50529542, 4143317495, 235803164, 1633788866, 892690282, 1465383342, 3115962473, 2256965911, 3250673817, 488449850, 2661202215, 3789633753, 4177007595, 2560144171, 286339874, 1768537042, 3654906025, 2391705863, 2492770099, 2610673197, 505291324, 2273808917, 3924369609, 3469625735, 1431699370, 673740880, 3755965093, 2358021891, 2711746649, 2307489801, 218961690, 3217021541, 3873845719, 1111672452, 1751693520, 1094828930, 2576986153, 757954394, 252645662, 2964376443, 1414855848, 3149649517, 370555436])

Te4 = map(Integer,[1667457891, 2088533116, 2004318071, 2071690107, 4076008178, 1802201963, 1869573999, 3318072773, 808464432, 16843009, 1734829927, 724249387, 4278124286, 3621246935, 2880154539, 1987475062, 3402287818, 2189591170, 3385444809, 2105376125, 4210752250, 1499027801, 1195853639, 4042322160, 2913840557, 3570717908, 2728567458, 2947526575, 2627509404, 2762253476, 1920103026, 3233857728, 3082270647, 4261281277, 2475922323, 640034342, 909522486, 1061109567, 4160223223, 3435973836, 875836468, 2779096485, 3857049061, 4059165169, 1903260017, 3638089944, 825307441, 353703189, 67372036, 3351758791, 589505315, 3284386755, 404232216, 2526451350, 84215045, 2593823386, 117901063, 303174162, 2155905152, 3806520034, 3958107115, 656877351, 2998055602, 1970632053, 151587081, 2206434179, 741092396, 437918234, 454761243, 1852730990, 1515870810, 2694881440, 1381126738, 993737531, 3604403926, 3014898611, 690563369, 3823363043, 791621423, 2223277188, 1397969747, 3520188881, 0, 3991793133, 538976288, 4244438268, 2981212593, 1532713819, 1785358954, 3419130827, 3200171710, 960051513, 1246382666, 1280068684, 1482184792, 3486502863, 3503345872, 4025479151, 2863311530, 4227595259, 1128481603, 1296911693, 858993459, 2240120197, 1162167621, 4193909241, 33686018, 2139062143, 1347440720, 1010580540, 2678038431, 2829625512, 1364283729, 2745410467, 1077952576, 2408550287, 2459079314, 2644352413, 943208504, 4126537205, 3166485692, 3065427638, 3671775962, 555819297, 269488144, 4294967295, 4092851187, 3537031890, 3452816845, 202116108, 320017171, 3974950124, 1600085855, 2543294359, 1145324612, 387389207, 3301229764, 2812782503, 2122219134, 1027423549, 1684300900, 1566399837, 421075225, 1936946035, 1616928864, 2172748161, 1330597711, 3705461980, 572662306, 707406378, 2425393296, 2290649224, 1179010630, 4008636142, 3099113656, 336860180, 3739147998, 1583242846, 185273099, 3688618971, 3772834016, 842150450, 976894522, 168430090, 1229539657, 101058054, 606348324, 1549556828, 3267543746, 3553874899, 2896997548, 1650614882, 2442236305, 2509608341, 3840206052, 2038004089, 3890735079, 3368601800, 926365495, 1835887981, 2374864269, 3587560917, 1313754702, 2846468521, 1819044972, 1448498774, 4109694196, 3941264106, 1701143909, 2054847098, 2930683566, 134744072, 3132799674, 2021161080, 623191333, 774778414, 471604252, 2795939494, 3031741620, 3334915782, 3907578088, 3722304989, 1953789044, 522133279, 1263225675, 3183328701, 2341178251, 2324335242, 1886417008, 1044266558, 3048584629, 1717986918, 1212696648, 50529027, 4143380214, 235802126, 1633771873, 892679477, 1465341783, 3115956665, 2256963206, 3250700737, 488447261, 2661195422, 3789677025, 4177066232, 2560137368, 286331153, 1768515945, 3654932953, 2391707278, 2492765332, 2610666395, 505290270, 2273806215, 3924421097, 3469659854, 1431655765, 673720360, 3755991007, 2358021260, 2711724449, 2307492233, 218959117, 3217014719, 3873892070, 1111638594, 1751672936, 1094795585, 2576980377, 757935405, 252645135, 2964369584, 1414812756, 3149642683, 370546198])

Td0 = map(Integer,[1374988112, 2118214995, 437757123, 975658646, 1001089995, 530400753, 2902087851, 1273168787, 540080725, 2910219766, 2295101073, 4110568485, 1340463100, 3307916247, 641025152, 3043140495, 3736164937, 632953703, 1172967064, 1576976609, 3274667266, 2169303058, 2370213795, 1809054150, 59727847, 361929877, 3211623147, 2505202138, 3569255213, 1484005843, 1239443753, 2395588676, 1975683434, 4102977912, 2572697195, 666464733, 3202437046, 4035489047, 3374361702, 2110667444, 1675577880, 3843699074, 2538681184, 1649639237, 2976151520, 3144396420, 4269907996, 4178062228, 1883793496, 2403728665, 2497604743, 1383856311, 2876494627, 1917518562, 3810496343, 1716890410, 3001755655, 800440835, 2261089178, 3543599269, 807962610, 599762354, 33778362, 3977675356, 2328828971, 2809771154, 4077384432, 1315562145, 1708848333, 101039829, 3509871135, 3299278474, 875451293, 2733856160, 92987698, 2767645557, 193195065, 1080094634, 1584504582, 3178106961, 1042385657, 2531067453, 3711829422, 1306967366, 2438237621, 1908694277, 67556463, 1615861247, 429456164, 3602770327, 2302690252, 1742315127, 2968011453, 126454664, 3877198648, 2043211483, 2709260871, 2084704233, 4169408201, 0, 159417987, 841739592, 504459436, 1817866830, 4245618683, 260388950, 1034867998, 908933415, 168810852, 1750902305, 2606453969, 607530554, 202008497, 2472011535, 3035535058, 463180190, 2160117071, 1641816226, 1517767529, 470948374, 3801332234, 3231722213, 1008918595, 303765277, 235474187, 4069246893, 766945465, 337553864, 1475418501, 2943682380, 4003061179, 2743034109, 4144047775, 1551037884, 1147550661, 1543208500, 2336434550, 3408119516, 3069049960, 3102011747, 3610369226, 1113818384, 328671808, 2227573024, 2236228733, 3535486456, 2935566865, 3341394285, 496906059, 3702665459, 226906860, 2009195472, 733156972, 2842737049, 294930682, 1206477858, 2835123396, 2700099354, 1451044056, 573804783, 2269728455, 3644379585, 2362090238, 2564033334, 2801107407, 2776292904, 3669462566, 1068351396, 742039012, 1350078989, 1784663195, 1417561698, 4136440770, 2430122216, 775550814, 2193862645, 2673705150, 1775276924, 1876241833, 3475313331, 3366754619, 270040487, 3902563182, 3678124923, 3441850377, 1851332852, 3969562369, 2203032232, 3868552805, 2868897406, 566021896, 4011190502, 3135740889, 1248802510, 3936291284, 699432150, 832877231, 708780849, 3332740144, 899835584, 1951317047, 4236429990, 3767586992, 866637845, 4043610186, 1106041591, 2144161806, 395441711, 1984812685, 1139781709, 3433712980, 3835036895, 2664543715, 1282050075, 3240894392, 1181045119, 2640243204, 25965917, 4203181171, 4211818798, 3009879386, 2463879762, 3910161971, 1842759443, 2597806476, 933301370, 1509430414, 3943906441, 3467192302, 3076639029, 3776767469, 2051518780, 2631065433, 1441952575, 404016761, 1942435775, 1408749034, 1610459739, 3745345300, 2017778566, 3400528769, 3110650942, 941896748, 3265478751, 371049330, 3168937228, 675039627, 4279080257, 967311729, 135050206, 3635733660, 1683407248, 2076935265, 3576870512, 1215061108, 3501741890])

Td1 = map(Integer,[1347548327, 1400783205, 3273267108, 2520393566, 3409685355, 4045380933, 2880240216, 2471224067, 1428173050, 4138563181, 2441661558, 636813900, 4233094615, 3620022987, 2149987652, 2411029155, 1239331162, 1730525723, 2554718734, 3781033664, 46346101, 310463728, 2743944855, 3328955385, 3875770207, 2501218972, 3955191162, 3667219033, 768917123, 3545789473, 692707433, 1150208456, 1786102409, 2029293177, 1805211710, 3710368113, 3065962831, 401639597, 1724457132, 3028143674, 409198410, 2196052529, 1620529459, 1164071807, 3769721975, 2226875310, 486441376, 2499348523, 1483753576, 428819965, 2274680428, 3075636216, 598438867, 3799141122, 1474502543, 711349675, 129166120, 53458370, 2592523643, 2782082824, 4063242375, 2988687269, 3120694122, 1559041666, 730517276, 2460449204, 4042459122, 2706270690, 3446004468, 3573941694, 533804130, 2328143614, 2637442643, 2695033685, 839224033, 1973745387, 957055980, 2856345839, 106852767, 1371368976, 4181598602, 1033297158, 2933734917, 1179510461, 3046200461, 91341917, 1862534868, 4284502037, 605657339, 2547432937, 3431546947, 2003294622, 3182487618, 2282195339, 954669403, 3682191598, 1201765386, 3917234703, 3388507166, 0, 2198438022, 1211247597, 2887651696, 1315723890, 4227665663, 1443857720, 507358933, 657861945, 1678381017, 560487590, 3516619604, 975451694, 2970356327, 261314535, 3535072918, 2652609425, 1333838021, 2724322336, 1767536459, 370938394, 182621114, 3854606378, 1128014560, 487725847, 185469197, 2918353863, 3106780840, 3356761769, 2237133081, 1286567175, 3152976349, 4255350624, 2683765030, 3160175349, 3309594171, 878443390, 1988838185, 3704300486, 1756818940, 1673061617, 3403100636, 272786309, 1075025698, 545572369, 2105887268, 4174560061, 296679730, 1841768865, 1260232239, 4091327024, 3960309330, 3497509347, 1814803222, 2578018489, 4195456072, 575138148, 3299409036, 446754879, 3629546796, 4011996048, 3347532110, 3252238545, 4270639778, 915985419, 3483825537, 681933534, 651868046, 2755636671, 3828103837, 223377554, 2607439820, 1649704518, 3270937875, 3901806776, 1580087799, 4118987695, 3198115200, 2087309459, 2842678573, 3016697106, 1003007129, 2802849917, 1860738147, 2077965243, 164439672, 4100872472, 32283319, 2827177882, 1709610350, 2125135846, 136428751, 3874428392, 3652904859, 3460984630, 3572145929, 3593056380, 2939266226, 824852259, 818324884, 3224740454, 930369212, 2801566410, 2967507152, 355706840, 1257309336, 4148292826, 243256656, 790073846, 2373340630, 1296297904, 1422699085, 3756299780, 3818836405, 457992840, 3099667487, 2135319889, 77422314, 1560382517, 1945798516, 788204353, 1521706781, 1385356242, 870912086, 325965383, 2358957921, 2050466060, 2388260884, 2313884476, 4006521127, 901210569, 3990953189, 1014646705, 1503449823, 1062597235, 2031621326, 3212035895, 3931371469, 1533017514, 350174575, 2256028891, 2177544179, 1052338372, 741876788, 1606591296, 1914052035, 213705253, 2334669897, 1107234197, 1899603969, 3725069491, 2631447780, 2422494913, 1635502980, 1893020342, 1950903388, 1120974935])

Td2 = map(Integer,[2807058932, 1699970625, 2764249623, 1586903591, 1808481195, 1173430173, 1487645946, 59984867, 4199882800, 1844882806, 1989249228, 1277555970, 3623636965, 3419915562, 1149249077, 2744104290, 1514790577, 459744698, 244860394, 3235995134, 1963115311, 4027744588, 2544078150, 4190530515, 1608975247, 2627016082, 2062270317, 1507497298, 2200818878, 567498868, 1764313568, 3359936201, 2305455554, 2037970062, 1047239000, 1910319033, 1337376481, 2904027272, 2892417312, 984907214, 1243112415, 830661914, 861968209, 2135253587, 2011214180, 2927934315, 2686254721, 731183368, 1750626376, 4246310725, 1820824798, 4172763771, 3542330227, 48394827, 2404901663, 2871682645, 671593195, 3254988725, 2073724613, 145085239, 2280796200, 2779915199, 1790575107, 2187128086, 472615631, 3029510009, 4075877127, 3802222185, 4107101658, 3201631749, 1646252340, 4270507174, 1402811438, 1436590835, 3778151818, 3950355702, 3963161475, 4020912224, 2667994737, 273792366, 2331590177, 104699613, 95345982, 3175501286, 2377486676, 1560637892, 3564045318, 369057872, 4213447064, 3919042237, 1137477952, 2658625497, 1119727848, 2340947849, 1530455833, 4007360968, 172466556, 266959938, 516552836, 0, 2256734592, 3980931627, 1890328081, 1917742170, 4294704398, 945164165, 3575528878, 958871085, 3647212047, 2787207260, 1423022939, 775562294, 1739656202, 3876557655, 2530391278, 2443058075, 3310321856, 547512796, 1265195639, 437656594, 3121275539, 719700128, 3762502690, 387781147, 218828297, 3350065803, 2830708150, 2848461854, 428169201, 122466165, 3720081049, 1627235199, 648017665, 4122762354, 1002783846, 2117360635, 695634755, 3336358691, 4234721005, 4049844452, 3704280881, 2232435299, 574624663, 287343814, 612205898, 1039717051, 840019705, 2708326185, 793451934, 821288114, 1391201670, 3822090177, 376187827, 3113855344, 1224348052, 1679968233, 2361698556, 1058709744, 752375421, 2431590963, 1321699145, 3519142200, 2734591178, 188127444, 2177869557, 3727205754, 2384911031, 3215212461, 2648976442, 2450346104, 3432737375, 1180849278, 331544205, 3102249176, 4150144569, 2952102595, 2159976285, 2474404304, 766078933, 313773861, 2570832044, 2108100632, 1668212892, 3145456443, 2013908262, 418672217, 3070356634, 2594734927, 1852171925, 3867060991, 3473416636, 3907448597, 2614737639, 919489135, 164948639, 2094410160, 2997825956, 590424639, 2486224549, 1723872674, 3157750862, 3399941250, 3501252752, 3625268135, 2555048196, 3673637356, 1343127501, 4130281361, 3599595085, 2957853679, 1297403050, 81781910, 3051593425, 2283490410, 532201772, 1367295589, 3926170974, 895287692, 1953757831, 1093597963, 492483431, 3528626907, 1446242576, 1192455638, 1636604631, 209336225, 344873464, 1015671571, 669961897, 3375740769, 3857572124, 2973530695, 3747192018, 1933530610, 3464042516, 935293895, 3454686199, 2858115069, 1863638845, 3683022916, 4085369519, 3292445032, 875313188, 1080017571, 3279033885, 621591778, 1233856572, 2504130317, 24197544, 3017672716, 3835484340, 3247465558, 2220981195, 3060847922, 1551124588, 1463996600])

Td3 = map(Integer,[4104605777, 1097159550, 396673818, 660510266, 2875968315, 2638606623, 4200115116, 3808662347, 821712160, 1986918061, 3430322568, 38544885, 3856137295, 718002117, 893681702, 1654886325, 2975484382, 3122358053, 3926825029, 4274053469, 796197571, 1290801793, 1184342925, 3556361835, 2405426947, 2459735317, 1836772287, 1381620373, 3196267988, 1948373848, 3764988233, 3385345166, 3263785589, 2390325492, 1480485785, 3111247143, 3780097726, 2293045232, 548169417, 3459953789, 3746175075, 439452389, 1362321559, 1400849762, 1685577905, 1806599355, 2174754046, 137073913, 1214797936, 1174215055, 3731654548, 2079897426, 1943217067, 1258480242, 529487843, 1437280870, 3945269170, 3049390895, 3313212038, 923313619, 679998000, 3215307299, 57326082, 377642221, 3474729866, 2041877159, 133361907, 1776460110, 3673476453, 96392454, 878845905, 2801699524, 777231668, 4082475170, 2330014213, 4142626212, 2213296395, 1626319424, 1906247262, 1846563261, 562755902, 3708173718, 1040559837, 3871163981, 1418573201, 3294430577, 114585348, 1343618912, 2566595609, 3186202582, 1078185097, 3651041127, 3896688048, 2307622919, 425408743, 3371096953, 2081048481, 1108339068, 2216610296, 0, 2156299017, 736970802, 292596766, 1517440620, 251657213, 2235061775, 2933202493, 758720310, 265905162, 1554391400, 1532285339, 908999204, 174567692, 1474760595, 4002861748, 2610011675, 3234156416, 3693126241, 2001430874, 303699484, 2478443234, 2687165888, 585122620, 454499602, 151849742, 2345119218, 3064510765, 514443284, 4044981591, 1963412655, 2581445614, 2137062819, 19308535, 1928707164, 1715193156, 4219352155, 1126790795, 600235211, 3992742070, 3841024952, 836553431, 1669664834, 2535604243, 3323011204, 1243905413, 3141400786, 4180808110, 698445255, 2653899549, 2989552604, 2253581325, 3252932727, 3004591147, 1891211689, 2487810577, 3915653703, 4237083816, 4030667424, 2100090966, 865136418, 1229899655, 953270745, 3399679628, 3557504664, 4118925222, 2061379749, 3079546586, 2915017791, 983426092, 2022837584, 1607244650, 2118541908, 2366882550, 3635996816, 972512814, 3283088770, 1568718495, 3499326569, 3576539503, 621982671, 2895723464, 410887952, 2623762152, 1002142683, 645401037, 1494807662, 2595684844, 1335535747, 2507040230, 4293295786, 3167684641, 367585007, 3885750714, 1865862730, 2668221674, 2960971305, 2763173681, 1059270954, 2777952454, 2724642869, 1320957812, 2194319100, 2429595872, 2815956275, 77089521, 3973773121, 3444575871, 2448830231, 1305906550, 4021308739, 2857194700, 2516901860, 3518358430, 1787304780, 740276417, 1699839814, 1592394909, 2352307457, 2272556026, 188821243, 1729977011, 3687994002, 274084841, 3594982253, 3613494426, 2701949495, 4162096729, 322734571, 2837966542, 1640576439, 484830689, 1202797690, 3537852828, 4067639125, 349075736, 3342319475, 4157467219, 4255800159, 1030690015, 1155237496, 2951971274, 1757691577, 607398968, 2738905026, 499347990, 3794078908, 1011452712, 227885567, 2818666809, 213114376, 3034881240, 1455525988, 3414450555, 850817237, 1817998408, 3092726480])

Td4 = map(Integer,[1381126738, 151587081, 1785358954, 3587560917, 808464432, 909522486, 2779096485, 943208504, 3217014719, 1077952576, 2745410467, 2661195422, 2172748161, 4092851187, 3621246935, 4227595259, 2088533116, 3823363043, 960051513, 2189591170, 2610666395, 791621423, 4294967295, 2273806215, 875836468, 2391707278, 1128481603, 1145324612, 3301229764, 3739147998, 3924421097, 3419130827, 1414812756, 2071690107, 2492765332, 842150450, 2795939494, 3267543746, 589505315, 1027423549, 4008636142, 1280068684, 2509608341, 185273099, 1111638594, 4210752250, 3284386755, 1313754702, 134744072, 774778414, 2711724449, 1717986918, 673720360, 3654932953, 606348324, 2998055602, 1987475062, 1532713819, 2728567458, 1229539657, 1835887981, 2341178251, 3520188881, 623191333, 1920103026, 4177066232, 4143380214, 1684300900, 2256963206, 1751672936, 2560137368, 370546198, 3570717908, 2762253476, 1549556828, 3435973836, 1566399837, 1701143909, 3065427638, 2459079314, 1819044972, 1886417008, 1212696648, 1347440720, 4261281277, 3991793133, 3115956665, 3671775962, 1583242846, 353703189, 1179010630, 1465341783, 2812782503, 2374864269, 2644352413, 2223277188, 2425393296, 3638089944, 2880154539, 0, 2358021260, 3166485692, 3553874899, 168430090, 4160223223, 3840206052, 1482184792, 84215045, 3099113656, 3014898611, 1162167621, 101058054, 3503345872, 741092396, 505290270, 2408550287, 3402287818, 1061109567, 252645135, 33686018, 3250700737, 2947526575, 3183328701, 50529027, 16843009, 320017171, 2324335242, 1802201963, 976894522, 2442236305, 286331153, 1094795585, 1330597711, 1734829927, 3705461980, 3941264106, 2543294359, 4076008178, 3486502863, 3469659854, 4042322160, 3031741620, 3873892070, 1936946035, 2526451350, 2896997548, 1953789044, 572662306, 3890735079, 2913840557, 892679477, 2240120197, 3806520034, 4193909241, 926365495, 3907578088, 471604252, 1970632053, 3755991007, 1852730990, 1195853639, 4059165169, 437918234, 1903260017, 488447261, 690563369, 3318072773, 2307492233, 1869573999, 3082270647, 1650614882, 235802126, 2863311530, 404232216, 3200171710, 454761243, 4244438268, 1448498774, 1044266558, 1263225675, 3334915782, 3537031890, 2038004089, 538976288, 2593823386, 3688618971, 3233857728, 4278124286, 2021161080, 3452816845, 1515870810, 4109694196, 522133279, 3722304989, 2829625512, 858993459, 2290649224, 117901063, 3351758791, 825307441, 2981212593, 303174162, 269488144, 1499027801, 656877351, 2155905152, 3974950124, 1600085855, 1616928864, 1364283729, 2139062143, 2846468521, 421075225, 3048584629, 1246382666, 218959117, 757935405, 3857049061, 2054847098, 2678038431, 2475922323, 3385444809, 2627509404, 4025479151, 2694881440, 3772834016, 993737531, 1296911693, 2930683566, 707406378, 4126537205, 2964369584, 3368601800, 3958107115, 3149642683, 1010580540, 2206434179, 1397969747, 2576980377, 1633771873, 387389207, 724249387, 67372036, 2122219134, 3132799674, 2004318071, 3604403926, 640034342, 3789677025, 1768515945, 336860180, 1667457891, 1431655765, 555819297, 202116108, 2105376125])

rcon = map(Integer,[16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 452984832, 905969664])



def Shift_Left(value,amount):
    """
    sage: Shift_Left(8,3)
    64
    sage: Shift_Left(7287,3)
    58296
    sage: Shift_Left(7287,32)
    0
    sage: Shift_Left(7287,15)
    238780416
    sage: Shift_Left(3249,15)
    106463232
    sage: Shift_Left(3249,33)
    0
    sage: Shift_Left(73249,0)
    73249
    sage: Shift_Left(Shift_Right(8173,0),0)
    8173
    sage: Shift_Left(Shift_Right(8173,5),5)
    8160

    sage: Shift_Left(Shift_Right(81722343,5),5)
    81722336
    """

    assert amount >= 0  #amount is a natural number

    if amount >= 32:
        result = 0
    else:
        result = value * (2 ** amount)

    assert is_word(result)
    return result


def Shift_Right(value,amount):
    """
    sage: Shift_Right(173249,18)
    0
    sage: Shift_Right(173,18)
    0
    sage: Shift_Right(8173,18)
    0
    sage: Shift_Right(8173,14)
    0
    sage: Shift_Right(81730,14)
    4
    sage: Shift_Right(81730,7)
    638
    sage:  Shift_Right(8173,0)
    8173
    sage: Shift_Right(Shift_Left(73249,8),8)
    73249
    sage: Shift_Right(Shift_Left(7343249,8),8)
    7343249
    sage: Shift_Right(Shift_Left(7343240,8),8)
    7343240
    

    """
    
    if amount >= 32:
        result = 0
    else:
        result = value // (2 ** amount)

    assert is_word(result)
    return result

def CombineWord(b0,b1,b2,b3):
    """
    sage: CombineWord(0, 182,0, 0)
    11927552
    sage: CombineWord(4, 182, 21, 109)
    79041901
    sage: CombineWord(14, 182, 251, 139)
    246872971
    sage: CombineWord(14, 182, 255, 139)
    246873995
    sage: CombineWord(104, 182, 255, 239)
    1756823535
    sage: SplitWord(CombineWord(104, 182, 255, 239))
    (104, 182, 255, 239)
    sage: SplitWord(CombineWord(4, 12, 255, 4))
    (4, 12, 255, 4)
    """
    assert CM.vall([b0,b1,b2,b3],is_byte)
    result = myxor([Shift_Left(b0,24),Shift_Left(b1,16),Shift_Left(b2,8),b3])
    assert is_word(result)

    return result


def SplitWord(w):
    """
    sage: SplitWord(731489134)
    (43, 153, 163, 110)
    sage: SplitWord(14934)
    (0, 0, 58, 86)
    sage: SplitWord(8914934)
    (0, 136, 7, 246)
    sage: SplitWord(29034904)
    (1, 187, 9, 152)
    sage: SplitWord(79034901)
    (4, 181, 250, 21)
    sage: SplitWord(79041901)
    (4, 182, 21, 109)
    sage:  CombineWord(*SplitWord(1783423))
    1783423
    sage:  CombineWord(*SplitWord(488953))
    488953
    sage:  CombineWord(*SplitWord(4742889))
    4742889
    """
    assert is_word(w)
    b0 = Shift_Right(w,24)
    b1 = myand([Shift_Right(w,16),255])
    b2 = myand([Shift_Right(w,8),255])
    b3 = myand([w,255])
    assert CM.vall([b0,b1,b2,b3],is_byte)
    return (b0,b1,b2,b3)


def KeySetupEnc(cipherKey,Nk):   #NK = 4,6,8
    """
    sage: KeySetupEnc([1,3,4,255,1,2,3,4,7,8,10,52,0,1,2,15,   1,3,4,255,1,2,3,4,7,8,10,52,0,1,2,15],6)
    ([16975103, 16909060, 117967412, 66063, 16975103, 16909060, 117967412, 66063, 1903361971, 1903427004, 1886452035, 1903360583, 894785056, 1127195559, 844979220, 1127129512, 861821163, 1110221484, 1081067276, 54551723, 823998655, 1915984151, 1097712124, 54616912, 3415512183, 3369398492, 4190750819, 2348437876, 3398930568, 3386307544, 765064618, 3847030134, 478465301, 2541657185, 1575554281, 2487222065, 2022650504, 2646751230, 2168912619, 372795018, 1272015459, 3756954962, 279261718, 2372339176, 203554563, 437885321, 1372124138, 2384881336, 1737907727, 3941686247, 3872433380, 4241046893, 0, 0, 0, 0, 0, 0, 0, 0], 12)


    sage:  KeySetupEnc([89,32,4,90,1,213,16,4,34,8,80,13,0,1,0,132,   82,28,76,21,132,48,89,123,90,80,12,12,10,8,40,65],6)
    ([1495270490, 30740484, 570970125, 65668, 1377586197, 2217761147, 1515195404, 168306753, 2134271244, 2134336904, 757803421, 2837147878, 4055542742, 2894372567, 3551722459, 2894437971, 2175711182, 683001640, 545038306, 2365063477, 1598749422, 4090455229, 1919013747, 1523848283, 1619437148, 3967723369, 3006553479, 1090206010, 849013321, 1750007314, 1597861657, 3007563888, 7837175, 1082961101, 1914062468, 442022038, 357695419, 2786211787, 2791678524, 3874033393, 2499758197, 2393370851, 165539490, 2949634409, 162167637, 4014175652, 2075934161, 4112239922, 643878212, 2309952557, 2147839864, 1866865372, 0, 0, 0, 0, 0, 0, 0, 0], 12)



    sage:  KeySetupEnc([89,32,4,90,1,213,16,4,34,8,80,13,0,1,0,132,   82,28,76,21,132,48,89,123,90,80,12,12,10,8,40,65],4)
    ([1495270490, 30740484, 570970125, 65668, 1377586197, 2217761147, 1515195404, 168306753, 4260157180, 3631914433, 3756295921, 3631979845, 3635591325, 13116764, 3744244653, 123158248, 2332042072, 2345141764, 1424270761, 1404279617, 4128546997, 2111612593, 691536664, 2055968857, 3948047215, 2525941214, 3216428742, 3309131423, 2363732169, 443383063, 2782639057, 1625744718, 2184879897, 2555896334, 1032606175, 1567274129, 2612469333, 65076315, 1047309700, 1661344021, 3261286318, 3246636021, 4293858929, 2632519524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10)
    sage:  KeySetupEnc([89,32,4,90,1,213,16,4,34,8,80,13,0,1,0,132,   82,28,76,21,132,48,89,123,90,80,12,12,10,8,40,65],8)
    ([1495270490, 30740484, 570970125, 65668, 1377586197, 2217761147, 1515195404, 168306753, 1746175805, 1774294841, 1271514932, 1271449520, 3790899954, 1707398025, 1066721157, 899479492, 3028065195, 3720154258, 2524236710, 3720088598, 546403509, 1163241276, 2059499705, 1331531645, 4228867119, 565340349, 3083248411, 1786425101, 575343970, 1730062942, 501207783, 1384275354, 3879984175, 3337729170, 1899435913, 458078340, 2376622397, 3937848163, 4150860164, 2783659038, 509128233, 3634961083, 2845707570, 3000219062, 3134108787, 1350074128, 2802935444, 49947274, 332124254, 3412249317, 1660733399, 3492770401, 3403412636, 2594409356, 1035136280, 1061736338, 21077803, 3391313358, 2833224217, 2029052024], 14)


    sage: KeySetupEnc([176, 158, 88, 202, 240, 198, 220, 226, 108, 39, 130, 15, 202, 223, 40, 95, 57, 208, 145, 169, 12, 57, 190, 59, 32, 123, 104, 23, 127, 193, 211, 98],6)
    ([2963167434, 4039564514, 1814528527, 3403622495, 969970089, 205110843, 544958487, 2143408994, 1070720217, 4111387782, 3437124911, 3236422420, 891371662, 1725376088, 1493615233, 2886209031, 1624658728, 2687610940, 4140215150, 2417069366, 3373748151, 1696547248, 97063576, 2784535204, 3221021288, 804089694, 3875152105, 2212847961, 2251060161, 601149797, 3888295758, 3358572560, 785768697, 2905637280, 723317345, 147333892, 803495294, 3888881006, 3374218647, 1680800823, 1328680534, 1207577938, 1111252446, 2784477360, 1827257639, 147276048, 1207258950, 1008148, 3029772221, 291596045, 2106120746, 1968151354, 0, 0, 0, 0, 0, 0, 0, 0], 12)

    sage: KeySetupEnc([176, 158, 88, 202, 240, 198, 220, 226, 108, 39, 130, 15, 202, 223, 40, 95, 57, 208, 145, 169, 12, 57, 190, 59, 32, 123, 104, 23, 127, 193, 211, 98],8)
    ([2963167434, 4039564514, 1814528527, 3403622495, 969970089, 205110843, 544958487, 2143408994, 3388535320, 960376570, 1427746037, 2680587434, 3798257157, 3999100990, 3458603049, 2984758091, 1608991184, 1725525802, 868271071, 2886092661, 1930129048, 2639666854, 1399850639, 3801599428, 3545914696, 3045274210, 2252599741, 709211848, 2523209840, 187907798, 1480800345, 3134518685, 2478572476, 641675742, 2692530275, 2319021739, 3900119058, 3812894404, 3137805981, 30665472, 3847577792, 3278524702, 1662423421, 3912230870, 4133653732, 354855456, 2921444541, 2951897021, 1285167801, 2414889895, 3974552282, 97074444, 2646584090, 2291728698, 649639303, 2303388218, 3659373086, 1441649081, 3104508771, 3166844527], 14)

    sage: KeySetupEnc([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],4)
    ([3710121810, 4160106793, 2888798928, 1180932390, 4190660594, 2940922532, 3403547314, 1497402272, 3494710920, 7749545, 2086837336, 1175824015, 2372500946, 2367636091, 4051557923, 3077077164, 3235245179, 1305128448, 3166138403, 199166095, 1323671376, 53424464, 3214426483, 3024570876, 3470667741, 3455131277, 1919508478, 3324909058, 3214497897, 1919436516, 71962, 3324972824, 720369117, 1485288249, 1485220387, 2661918011, 3806926806, 3127813359, 3806858956, 2084678647, 1468760006, 3991264041, 252564965, 1934392850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10)

    sage: KeySetupEnc([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],6)
    ([3710121810, 4160106793, 2888798928, 1180932390, 4190660594, 2940922532, 3403547314, 1497402272, 1367154130, 387876084, 4007060230, 1100745122, 3601171624, 737610666, 2055870072, 1838453388, 2202169738, 3269359656, 3474567309, 3840850727, 2657398111, 4092608467, 1890733657, 2993436273, 2535199674, 1945282717, 3986032066, 510016017, 1859417160, 3703063097, 3945791804, 2562894241, 1968483427, 1798477426, 99017274, 3646857219, 2479913481, 185783208, 2118549451, 359983545, 278006659, 3385633664, 2561849300, 2476762236, 3991280567, 4170379790, 3892377997, 567038477, 1404198953, 3222406229, 770973666, 3580292588, 0, 0, 0, 0, 0, 0, 0, 0], 12)

    sage: KeySetupEnc([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],8)
    ([3710121810, 4160106793, 2888798928, 1180932390, 4190660594, 2940922532, 3403547314, 1497402272, 3575519129, 585639600, 2395452512, 3366202694, 293715880, 3200996620, 1947555774, 760601630, 731407681, 158352369, 2276980625, 1326701271, 2516379814, 725073322, 1596123668, 1920415242, 3667722753, 3555541488, 1415231073, 457796790, 986167528, 300942658, 1322446678, 1017502044, 3567798506, 121964826, 1394589563, 1213649869, 1752620629, 2038881047, 928265281, 200404253, 1711140033, 1656284635, 833051296, 2045872493, 3738663273, 2807145086, 2416285247, 2616490786, 4208754645, 2556729870, 2848178350, 3492956611, 2935243335, 161865785, 2577430022, 39062820, 2584431010, 40883116, 2880180994, 2073975489], 14)


    """
    assert is_key(cipherKey)

    W = [0] * roundkey_index  #key_schedule


    Nr = Nk+6
    rk = [0] * roundkey_index #key_schedule
    i = 0
    W[0] = CombineWord(cipherKey[0 ],cipherKey[1 ],cipherKey[2 ],cipherKey[3])
    W[1] = CombineWord(cipherKey[4 ],cipherKey[5 ],cipherKey[6 ],cipherKey[7])
    W[2] = CombineWord(cipherKey[8 ],cipherKey[9 ],cipherKey[10],cipherKey[11])
    W[3] = CombineWord(cipherKey[12],cipherKey[13],cipherKey[14],cipherKey[15])

    _f = lambda p, n_,i : myxor([W[p-n_],
                                 myand([Te4[myand([Shift_Right(temp,16),255])], 4278190080]),
                                 myand([Te4[myand([Shift_Right(temp, 8),255])],   16711680]),
                                 myand([Te4[myand([            temp,    255])],      65280]),
                                 myand([Te4[       Shift_Right(temp,24)       ],       255]),
                                 rcon[i]
                                 ])
    if Nk == 4:
        p = 4
        while True:
            temp = W[p-1]
            W[p] = _f(p,4,i)

            W[p+1] = myxor([W[p-3],W[p]])
            W[p+2] = myxor([W[p-2],W[p+1]])
            W[p+3] = myxor([W[p-1],W[p+2]])
            i = i + 1
            if i >= 10:
                break
            p = p + 4 # p = 4*(i+1)
        #end while
        rk = W #endif
        


    W[4] = CombineWord(cipherKey[16],cipherKey[17],cipherKey[18],cipherKey[19])
    W[5] = CombineWord(cipherKey[20],cipherKey[21],cipherKey[22],cipherKey[23])
    
    if Nk == 6:
        p = 6
        while True:
            temp = W[p-1]
            W[p] = _f(p,6,i)
                       
            W[p+1] = myxor([W[p-5],W[p]])
            W[p+2] = myxor([W[p-4],W[p+1]])
            W[p+3] = myxor([W[p-3],W[p+2]])
            i = i + 1
            if i >= 8:
                break
            W[p+4] = myxor([W[p-2], W[p+3]])
            W[p+5] = myxor([W[p-1], W[p+4]])
            p = p + 6 #-- p = 6*(i+1)

        rk = W


    W[6] = CombineWord(cipherKey[24], cipherKey[25], cipherKey[26], cipherKey[27])
    W[7] = CombineWord(cipherKey[28], cipherKey[29], cipherKey[30], cipherKey[31])

    if Nk == 8 :
        p = 8
        while True:
            temp = W[p-1]
            W[p] = _f(p,8,i)
                       
            W[p+1] = myxor([W[p-7],W[p]])
            W[p+2] = myxor([W[p-6],W[p+1]])
            W[p+3] = myxor([W[p-5],W[p+2]])
            i = i + 1
            if i >= 7:
                break

            temp = W[p+3]
            W[p+4] = myxor([
                W[p-4],
                myand([Te4[     Shift_Right(temp,24)      ], 4278190080]),
                myand([Te4[myand([Shift_Right(temp,16),255])],   16711680]),
                myand([Te4[myand([Shift_Right(temp, 8),255])],      65280]),
                myand([Te4[myand([            temp,    255])],        255])
                ])
                         
            
            W[p+5] = myxor([W[p-3], W[p+4]])
            W[p+6] = myxor([W[p-2], W[p+5]])
            W[p+7] = myxor([W[p-1], W[p+6]])
            p = p + 8 #-- p = 8*(i+1)

        rk = W

    assert is_key_schedule(rk)
    return rk,Nr




def KeySetupDec(cipherKey,Nk):
    """
    sage: KeySetupDec([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],4)
    ([1468760006, 3991264041, 252564965, 1934392850, 3442653058, 2060992892, 3112034002, 858007120, 785854500, 3085629182, 3282411438, 2321152130, 3980534940, 2570962650, 1951361360, 1241278252, 4103653956, 1954538054, 3983716234, 1035144828, 60431079, 2162632706, 2567785932, 3502350838, 2765592422, 2206020325, 434791886, 1238166586, 2529095827, 665494915, 2593609515, 1344702964, 1731301314, 2970899728, 3174953640, 3400654559, 4190660594, 2940922532, 3403547314, 1497402272, 3710121810, 4160106793, 2888798928, 1180932390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10)

    sage: KeySetupDec([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],6)
    ([1404198953, 3222406229, 770973666, 3580292588, 3870311860, 1314812917, 2012955989, 1654091305, 967128736, 359410556, 1192033016, 1812385164, 930987716, 722089844, 2327218232, 2834183745, 2713501516, 576241273, 2437611745, 751377884, 3004415640, 3179420989, 1425369390, 477596080, 2508543335, 1216536734, 3184211708, 2212757813, 4115256930, 1043281865, 821542829, 244425637, 249071716, 1046879240, 1841618845, 3708270073, 4064419569, 2965596772, 676225947, 3412517291, 2559379967, 3811082800, 3317590479, 817796204, 4190660594, 2940922532, 3403547314, 1497402272, 3710121810, 4160106793, 2888798928, 1180932390, 0, 0, 0, 0, 0, 0, 0, 0], 12)

    sage: KeySetupDec([221, 35, 247, 82, 247, 246, 49, 41, 172, 47, 146, 208, 70, 99, 153, 38, 249, 200, 103, 242, 175, 74, 234, 164, 202, 222, 2, 178, 89, 64, 139, 160],8)
    ([2584431010, 40883116, 2880180994, 2073975489, 384320741, 865677551, 1301164218, 949471513, 338006575, 1983227023, 3863906091, 1479020809, 3079610883, 628192266, 2115436629, 1964636579, 910544392, 1645229728, 2423989156, 3194394146, 3957353714, 2466141705, 1533441119, 185530870, 504636913, 1414920360, 4067104004, 773698950, 1463260249, 2032024315, 3382190678, 1349029289, 1269570488, 1245830489, 2789141932, 3698761858, 2896404407, 774483618, 2961578157, 2582687743, 913526175, 32360161, 3967758581, 2051558702, 2005585078, 2190094613, 2662315535, 695646034, 645754480, 933137278, 3985831444, 2520219099, 4190660594, 2940922532, 3403547314, 1497402272, 3710121810, 4160106793, 2888798928, 1180932390], 14)


    sage: KeySetupDec([176, 158, 88, 202, 240, 198, 220, 226, 108, 39, 130, 15, 202, 223, 40, 95, 57, 208, 145, 169, 12, 57, 190, 59, 32, 123, 104, 23, 127, 193, 211, 98],4)
    ([1025160214, 302793970, 3386549779, 1781278839, 3444714004, 1383782354, 1528593975, 2370356671, 1530868256, 2670263750, 157723109, 3595877256, 2065877212, 3289894886, 2521715747, 3744600685, 1601015254, 3207923514, 1381604293, 1232881230, 3402885215, 3763899116, 3983318271, 455466379, 1071530852, 713777843, 221517331, 4131996020, 3553902103, 357900759, 666858656, 4219295591, 4052807602, 3330351040, 854218103, 3703710663, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10)

    sage: KeySetupDec([176, 158, 88, 202, 240, 198, 220, 226, 108, 39, 130, 15, 202, 223, 40, 95, 57, 208, 145, 169, 12, 57, 190, 59, 32, 123, 104, 23, 127, 193, 211, 98],6)
    ([3029772221, 291596045, 2106120746, 1968151354, 4088601667, 2963529299, 208955818, 287670732, 3168253945, 491907174, 2517592076, 2813822644, 2553946475, 834203320, 1409587959, 1125171728, 1706849359, 387209447, 4291261929, 2709938079, 3906153742, 1581329014, 681636799, 2843922387, 2373802336, 2166504556, 3426663324, 1923624104, 1293715440, 3197540148, 2591752614, 3063023480, 619550354, 753469150, 3851831759, 207578380, 2184796217, 3922275523, 1094968060, 4085911748, 2827669055, 2999579192, 3613886038, 134516812, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495, 0, 0, 0, 0, 0, 0, 0, 0], 12)

    sage: KeySetupDec([176, 158, 88, 202, 240, 198, 220, 226, 108, 39, 130, 15, 202, 223, 40, 95, 57, 208, 145, 169, 12, 57, 190, 59, 32, 123, 104, 23, 127, 193, 211, 98],8)
    ([3659373086, 1441649081, 3104508771, 3166844527, 1716678090, 3647538334, 3236237465, 138497303, 1224602676, 733860567, 2050250780, 844622707, 1809248947, 3208341844, 428610567, 3366215054, 751667576, 1665148643, 1367968459, 1214493551, 1903669283, 3572341735, 2797043027, 3509078409, 3349507230, 1334685595, 852077608, 434780580, 1232577087, 2778344388, 1918559924, 2006922458, 3289147709, 2284372741, 2101609395, 723752332, 1697218493, 3974990331, 3619736944, 96850542, 907442803, 1277471288, 4117545142, 1449629247, 1453842524, 2311386694, 992822411, 3523551006, 504924245, 2050150475, 3108530830, 2735429257, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495], 14)


    """
    assert is_key(cipherKey)

    rk,Nr = KeySetupEnc(cipherKey, Nk)
    i = 0
    j = 4*Nr;

    while i < j:
        temp = rk[i] 
        rk[i] = rk[j] 
        rk[j] = temp
        temp = rk[i+1] 
        rk[i+1] = rk[j+1] 
        rk[j+1] = temp
        temp = rk[i+2] 
        rk[i+2] = rk[j+2] 
        rk[j+2] = temp
        temp = rk[i+3] 
        rk[i+3] = rk[j+3] 
        rk[j+3] = temp
        i = i + 4 
        j = j - 4


    def _f(p,n_): 
        res = myxor([Td0[myand([Te4[      Shift_Right(rk[p+n_],24)        ], 255])],
                     Td1[myand([Te4[myand([Shift_Right(rk[p+n_],16), 255])], 255])],
                     Td2[myand([Te4[myand([Shift_Right(rk[p+n_],8),  255])], 255])],
                     Td3[myand([Te4[myand([            rk[p+n_],     255])], 255])]
                     ])

        return res
    
    p = 0
    for k in range(1,Nr-1):
        p = p + 4
        rk[p ]  = _f(p,0)
        rk[p+1] = _f(p,1)
        rk[p+2] = _f(p,2)
        rk[p+3] = _f(p,3)
                    

    assert is_key_schedule(rk)
    return rk,Nr


def AesKeySetupEnc(cipherKey,keyBits): #KeyBits = 128 ,192,256
    rk,Nr = KeySetupEnc(cipherKey,keyBits/32)
    return rk,Nr


def AesKeySetupDec(cipherKey,keyBits):
    rk,Nr = KeySetupDec(cipherKey, keyBits//32)
    return rk,Nr

def AesEncrypt(rk,Nr,pt,verbose=1):
    """
    sage: AesEncrypt([3659373086, 1441649081, 3104508771, 3166844527, 1716678090, 3647538334, 3236237465, 138497303, 1224602676, 733860567, 2050250780, 844622707, 1809248947, 3208341844, 428610567, 3366215054, 751667576, 1665148643, 1367968459, 1214493551, 1903669283, 3572341735, 2797043027, 3509078409, 3349507230, 1334685595, 852077608, 434780580, 1232577087, 2778344388, 1918559924, 2006922458, 3289147709, 2284372741, 2101609395, 723752332, 1697218493, 3974990331, 3619736944, 96850542, 907442803, 1277471288, 4117545142, 1449629247, 1453842524, 2311386694, 992822411, 3523551006, 504924245, 2050150475, 3108530830, 2735429257, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495],10,[255,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,1])
    [228, 176, 111, 153, 189, 67, 62, 60, 171, 23, 200, 92, 117, 240, 185, 202]

    sage: AesEncrypt([3659373086, 1441649081, 3104508771, 3166844527, 1716678090, 3647538334, 3236237465, 138497303, 1224602676, 733860567, 2050250780, 844622707, 1809248947, 3208341844, 428610567, 3366215054, 751667576, 1665148643, 1367968459, 1214493551, 1903669283, 3572341735, 2797043027, 3509078409, 3349507230, 1334685595, 852077608, 434780580, 1232577087, 2778344388, 1918559924, 2006922458, 3289147709, 2284372741, 2101609395, 723752332, 1697218493, 3974990331, 3619736944, 96850542, 907442803, 1277471288, 4117545142, 1449629247, 1453842524, 2311386694, 992822411, 3523551006, 504924245, 2050150475, 3108530830, 2735429257, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495],12,[255,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,1])
    [102, 134, 236, 148, 16, 162, 217, 167, 103, 208, 218, 18, 18, 156, 212, 81]

    sage: AesEncrypt([3659373086, 1441649081, 3104508771, 3166844527, 1716678090, 3647538334, 3236237465, 138497303, 1224602676, 733860567, 2050250780, 844622707, 1809248947, 3208341844, 428610567, 3366215054, 751667576, 1665148643, 1367968459, 1214493551, 1903669283, 3572341735, 2797043027, 3509078409, 3349507230, 1334685595, 852077608, 434780580, 1232577087, 2778344388, 1918559924, 2006922458, 3289147709, 2284372741, 2101609395, 723752332, 1697218493, 3974990331, 3619736944, 96850542, 907442803, 1277471288, 4117545142, 1449629247, 1453842524, 2311386694, 992822411, 3523551006, 504924245, 2050150475, 3108530830, 2735429257, 969970089, 205110843, 544958487, 2143408994, 2963167434, 4039564514, 1814528527, 3403622495],14,[255,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,1])
    [9, 24, 26, 240, 109, 194, 246, 135, 95, 32, 90, 192, 207, 165, 225, 237]

    sage: AesEncrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=14,pt=[255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
    [137, 68, 165, 70, 4, 134, 2, 246, 190, 149, 62, 139, 151, 51, 162, 29]
    
    
    sage: AesEncrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=14,pt=[255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
    [190, 133, 41, 204, 26, 57, 155, 114, 40, 153, 53, 218, 165, 165, 171, 233]
    
    sage: AesEncrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=10,pt=[255, 0, 28, 0, 1, 0, 0, 0, 0, 0, 0, 92, 5, 0, 11, 7])
    [74, 214, 59, 245, 196, 180, 42, 157, 33, 179, 23, 176, 232, 101, 117, 87]
    
    sage: AesEncrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=10,pt=[255, 0, 28, 0, 1, 0, 0, 0, 0, 0, 0, 92, 5, 0, 11, 7])
    [134, 38, 52, 252, 219, 97, 175, 255, 122, 211, 191, 61, 212, 188, 56, 192]

    sage: AesEncrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=10,pt=[255, 0, 28, 15, 199, 0, 254, 45, 0, 89, 0, 92, 52, 130, 171, 78])
    [132, 103, 42, 60, 76, 252, 70, 7, 127, 9, 121, 7, 171, 200, 170, 155]
    
    sage: AesEncrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=10,pt=[255, 0, 28, 15, 199, 0, 254, 45, 0, 89, 0, 92, 52, 130, 171, 78])
    [62, 227, 174, 225, 178, 225, 28, 216, 24, 109, 114, 125, 63, 176, 58, 81]
    
    
    """
    assert is_key_schedule(rk)
    assert is_block(pt)

    #assert allints(rk)
    #assert allints(pt)

    s0 = myxor([CombineWord(pt[ 0], pt[ 1], pt[ 2], pt[ 3]),rk[0]]);
    s1 = myxor([CombineWord(pt[ 4], pt[ 5], pt[ 6], pt[ 7]),rk[1]]);
    s2 = myxor([CombineWord(pt[ 8], pt[ 9], pt[10], pt[11]),rk[2]]);
    s3 = myxor([CombineWord(pt[12], pt[13], pt[14], pt[15]),rk[3]]);
    

    
    def _f(l0,l1,l2,l3, iv):
        
        _t0 = Te0[       Shift_Right(l0, 24)      ]
        _t1 = Te1[myand([Shift_Right(l1, 16),255])]
        _t2 = Te2[myand([Shift_Right(l2,  8),255])]
        _t3 = Te3[myand([l3,255])]
        _t4 = rk[iv]
        res = myxor([_t0,_t1,_t2,_t3,_t4])
        return res

    # round 1:
    t0 = _f(s0, s1, s2, s3, 4)
    t1 = _f(s1, s2, s3, s0, 5)
    t2 = _f(s2, s3, s0, s1, 6)
    t3 = _f(s3, s0, s1, s2, 7)

    # round 2:
    s0 = _f(t0, t1, t2, t3,  8)
    s1 = _f(t1, t2, t3, t0,  9)
    s2 = _f(t2, t3, t0, t1, 10)
    s3 = _f(t3, t0, t1, t2, 11)
 
    # round 3:
    t0 = _f(s0, s1, s2, s3, 12)
    t1 = _f(s1, s2, s3, s0, 13)
    t2 = _f(s2, s3, s0, s1, 14)
    t3 = _f(s3, s0, s1, s2, 15)

    # round 4:
    s0 = _f(t0, t1, t2, t3,16)
    s1 = _f(t1, t2, t3, t0,17)
    s2 = _f(t2, t3, t0, t1,18)
    s3 = _f(t3, t0, t1, t2,19)

    # round 5:
    t0 = _f(s0, s1, s2, s3, 20)
    t1 = _f(s1, s2, s3, s0, 21)
    t2 = _f(s2, s3, s0, s1, 22)
    t3 = _f(s3, s0, s1, s2, 23)
    
    # round 6:
    s0 = _f(t0, t1, t2, t3, 24)
    s1 = _f(t1, t2, t3, t0, 25)
    s2 = _f(t2, t3, t0, t1, 26)
    s3 = _f(t3, t0, t1, t2, 27)
    
    # round 7:
    t0 = _f(s0, s1, s2, s3, 28)
    t1 = _f(s1, s2, s3, s0, 29)
    t2 = _f(s2, s3, s0, s1, 30)
    t3 = _f(s3, s0, s1, s2, 31)
    
    # round 8:
    s0 = _f(t0, t1, t2, t3, 32)
    s1 = _f(t1, t2, t3, t0, 33)
    s2 = _f(t2, t3, t0, t1, 34)
    s3 = _f(t3, t0, t1, t2, 35)

    # round 9:
    t0 = _f(s0, s1,s2, s3, 36)
    t1 = _f(s1, s2,s3, s0, 37)
    t2 = _f(s2, s3,s0, s1, 38)
    t3 = _f(s3, s0,s1, s2, 39)
    
    if (Nr > 10):
     	# round 10:
        s0 = _f(t0, t1, t2, t3, 40)
        s1 = _f(t1, t2, t3, t0, 41)
        s2 = _f(t2, t3, t0, t1, 42)
        s3 = _f(t3, t0, t1, t2, 43)
        
      # round 11:                
        t0 = _f(s0, s1, s2, s3, 44)
        t1 = _f(s1, s2, s3, s0, 45)
        t2 = _f(s2, s3, s0, s1, 46)
        t3 = _f(s3, s0, s1, s2, 47)
    
    if (Nr > 12):
        # round 12               
        s0 = _f(t0, t1, t2, t3, 48)
        s1 = _f(t1, t2, t3, t0, 49)
        s2 = _f(t2, t3, t0, t1, 50)
        s3 = _f(t3, t0, t1, t2, 51)
                                 
        # round 13               
        t0 = _f(s0, s1, s2, s3, 52)
        t1 = _f(s1, s2, s3, s0, 53)
        t2 = _f(s2, s3, s0, s1, 54)
        t3 = _f(s3, s0, s1, s2, 55)


    # last round:
    _g = lambda l0,l1,l2,l3,iv: myxor([
            myand([Te4[       Shift_Right(l0,24)      ],4278190080]),
            myand([Te4[myand([Shift_Right(l1,16),255])],  16711680]),
            myand([Te4[myand([Shift_Right(l2, 8),255])],     65280]),
            myand([Te4[myand([            l3,    255])],       255]),
            rk[4*Nr+iv]
            ])

    s0 = _g(t0,t1,t2,t3,0)
    s1 = _g(t1,t2,t3,t0,1)
    s2 = _g(t2,t3,t0,t1,2)
    s3 = _g(t3,t0,t1,t2,3)


    # map cipher state to byte array block:
    #ct = block'(others => 0);
    ct = [0]*block_index
    b0,b1,b2,b3 = SplitWord(s0);
    ct[ 0] = b0 
    ct[ 1] = b1 
    ct[ 2] = b2 
    ct[ 3] = b3

    b0, b1, b2, b3 = SplitWord(s1);
    ct[ 4] = b0 
    ct[ 5] = b1 
    ct[ 6] = b2 
    ct[ 7] = b3

    b0, b1, b2, b3 = SplitWord(s2);
    ct[ 8] = b0
    ct[ 9] = b1
    ct[10] = b2
    ct[11] = b3

    b0, b1, b2, b3 = SplitWord(s3)
    ct[12] = b0
    ct[13] = b1
    ct[14] = b2
    ct[15] = b3

    print 'AesEncrypt(rk=%s,Nr=%d,pt=%s)'%(str(rk),Nr,str(pt))
    return ct


def AesDecrypt(rk,Nr,ct,verbose=1):
    #rk: in key_schedule; Nr: in Integer; ct: in block; pt: out block
    """
    
    sage: AesDecrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=14,ct=[137, 68, 165, 70, 4, 134, 2, 246, 190, 149, 62, 139, 151, 51, 162, 29])
    [255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
    
    sage: AesDecrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=14,ct=[190, 133, 41, 204, 26, 57, 155, 114, 40, 153, 53, 218, 165, 165, 171, 233])
    [190, 132, 45, 239, 43, 176, 158, 126, 154, 150, 56, 130, 112, 118, 173, 44]


    sage: AesDecrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=10,ct=[74, 214, 59, 245, 196, 180, 42, 157, 33, 179, 23, 176, 232, 101, 117, 87])
    [255, 0, 28, 0, 1, 0, 0, 0, 0, 0, 0, 92, 5, 0, 11, 7]
    
    sage: AesDecrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=10,ct=[134, 38, 52, 252, 219, 97, 175, 255, 122, 211, 191, 61, 212, 188, 56, 192])
    [244, 131, 177, 138, 183, 235, 64, 105, 135, 216, 54, 194, 103, 26, 124, 76]
    
    
    sage: AesDecrypt(rk=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],Nr=10,ct=[132, 103, 42, 60, 76, 252, 70, 7, 127, 9, 121, 7, 171, 200, 170, 155])
    [255, 0, 28, 15, 199, 0, 254, 45, 0, 89, 0, 92, 52, 130, 171, 78]
    
    
    sage: AesDecrypt(rk=[78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2, 78, 15, 93, 2],Nr=10,ct=[62, 227, 174, 225, 178, 225, 28, 216, 24, 109, 114, 125, 63, 176, 58, 81])
    [72, 104, 246, 161, 77, 186, 106, 178, 48, 218, 49, 247, 236, 181, 198, 163]
    
    """

    
    # map byte array block to cipher state
    # and add initial round key:
    s0 = myxor([CombineWord(ct[ 0], ct[ 1], ct[ 2], ct[ 3]), rk[0]]);
    s1 = myxor([CombineWord(ct[ 4], ct[ 5], ct[ 6], ct[ 7]), rk[1]]);
    s2 = myxor([CombineWord(ct[ 8], ct[ 9], ct[10], ct[11]), rk[2]]);
    s3 = myxor([CombineWord(ct[12], ct[13], ct[14], ct[15]), rk[3]]);
    
    _f = lambda l0,l1,l2,l3, iv: myxor([
            Td0[       Shift_Right(l0, 24)      ],
            Td1[myand([Shift_Right(l1, 16),255])],
            Td2[myand([Shift_Right(l2,  8),255])],
            Td3[myand([l3,255])],
            rk[iv]
            ])
    
     # round 1:
    t0 = _f(s0, s3, s2, s1,  4)
    t1 = _f(s1, s0, s3, s2,  5)
    t2 = _f(s2, s1, s0, s3,  6)
    t3 = _f(s3, s2, s1, s0,  7)
    
     # round 2:
    s0 = _f(t0, t3, t2, t1,  8)
    s1 = _f(t1, t0, t3, t2,  9)
    s2 = _f(t2, t1, t0, t3, 10)
    s3 = _f(t3, t2, t1, t0, 11)
    
     # round 3:
    t0 = _f(s0, s3, s2, s1, 12)
    t1 = _f(s1, s0, s3, s2, 13)
    t2 = _f(s2, s1, s0, s3, 14)
    t3 = _f(s3, s2, s1, s0, 15)
    
     # round 4:
    s0 = _f(t0, t3, t2, t1, 16)
    s1 = _f(t1, t0, t3, t2, 17)
    s2 = _f(t2, t1, t0, t3, 18)
    s3 = _f(t3, t2, t1, t0, 19)
    
    # round 5:
    t0 = _f(s0, s3, s2, s1, 20);
    t1 = _f(s1, s0, s3, s2, 21);
    t2 = _f(s2, s1, s0, s3, 22);
    t3 = _f(s3, s2, s1, s0, 23);
    
     # round 6:
    s0 = _f(t0, t3, t2, t1, 24);
    s1 = _f(t1, t0, t3, t2, 25);
    s2 = _f(t2, t1, t0, t3, 26);
    s3 = _f(t3, t2, t1, t0, 27);
    
     # roun 7:
    t0 = _f(s0, s3, s2, s1, 28);
    t1 = _f(s1, s0, s3, s2, 29);
    t2 = _f(s2, s1, s0, s3, 30);
    t3 = _f(s3, s2, s1, s0, 31);
    
    # 
    s0 = _f(t0, t3, t2, t1, 32);
    s1 = _f(t1, t0, t3, t2, 33);
    s2 = _f(t2, t1, t0, t3, 34);
    s3 = _f(t3, t2, t1, t0, 35);
    
    # roun
    t0 = _f(s0, s3, s2, s1, 36);
    t1 = _f(s1, s0, s3, s2, 37);
    t2 = _f(s2, s1, s0, s3, 38);
    t3 = _f(s3, s2, s1, s0, 39);
    
    if (Nr > 10) :
     	# round 10:
        s0 = _f(t0, t3, t2, t1, 40)
     	s1 = _f(t1, t0, t3, t2, 41)
        s2 = _f(t2, t1, t0, t3, 42)
        s3 = _f(t3, t2, t1, t0, 43)
        
        # round 11
        t0 = _f(s0, s3, s2, s1, 44)
     	t1 = _f(s1, s0, s3, s2, 45)
        t2 = _f(s2, s1, s0, s3, 46)
        t3 = _f(s3, s2, s1, s0, 47)

    if (Nr > 12):
        # round 12
        s0 = _f(t0, t3, t2, t1, 48)
       	s1 = _f(t1, t0, t3, t2, 49)
        s2 = _f(t2, t1, t0, t3, 50)
       	s3 = _f(t3, t2, t1, t0, 51)
        
        # roud 13
        t0 = _f(s0, s3, s2, s1, 52)
       	t1 = _f(s1, s0, s3, s2, 53)
        t2 = _f(s2, s1, s0, s3, 54)
        t3 = _f(s3, s2, s1, s0, 55)


    # last round:
    _g = lambda l0,l1,l2,l3,iv: myxor([
            myand([Td4[       Shift_Right(l0,24)      ],4278190080]),
            myand([Td4[myand([Shift_Right(l1,16),255])],  16711680]),
            myand([Td4[myand([Shift_Right(l2, 8),255])],     65280]),
            myand([Td4[myand([            l3,    255])],       255]),
            rk[4*Nr+iv]
            ])
    
    s0 = _g(t0,t3,t2,t1,0)
    s1 = _g(t1,t0,t3,t2,1)
    s2 = _g(t2,t1,t0,t3,2)
    s3 = _g(t3,t2,t1,t0,3)
    
    # map cipher state to byte array block:
    pt = [0]*block_index
    b0, b1, b2, b3 = SplitWord(s0);
    pt[ 0] = b0
    pt[ 1] = b1; 
    pt[ 2] = b2; 
    pt[ 3] = b3;
    
    b0, b1, b2, b3 = SplitWord(s1)
    pt[ 4] = b0; 
    pt[ 5] = b1; 
    pt[ 6] = b2; 
    pt[ 7] = b3;

    b0, b1, b2, b3 = SplitWord(s2);
    pt[ 8] = b0; 
    pt[ 9] = b1; 
    pt[10] = b2; 
    pt[11] = b3;
    
    b0, b1, b2, b3 = SplitWord(s3);
    pt[12] = b0; 
    pt[13] = b1; 
    pt[14] = b2; 
    pt[15] = b3;

    print 'AesDecrypt(rk=%s,Nr=%d,ct=%s)'%(str(rk),Nr,str(ct))

    return pt

def Driver(verbose=1):
    print("AES AesEncrypt 1")

    Rk = flatten([[0,0,0,0]]*(roundkey_index/4))
    Nr = 14
    Block1 = [255,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,1]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk    
    print(Block2)
   
   
   
    print("AES AesDecrypt 1")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    #print 'rk', Rk    
    print(Block1)


    print("AES AesEncrypt 1 - Cust")

    Rk = flatten([[78,15,93,2]]*(roundkey_index/4))
    Nr = 14
    Block1 = [255,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,1]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk    
    print(Block2)
   
   
   
    print("AES AesDecrypt 1 - Cust")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    print(Block1)


    ##############

    print("AES AesEncrypt 2")

    Rk = flatten([[0,0,0,0]]*(roundkey_index/4))
    Nr = 10
    Block1 = [255,0,28,0, 1,0,0,0, 0,0,0,92, 5,0,11,7]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk
    print(Block2)
   
   
   
    print("AES AesDecrypt 2")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    print(Block1)


    print("AES AesEncrypt 2 - Cust")

    Rk = flatten([[78,15,93,2]]*(roundkey_index/4))
    Nr = 10
    Block1 = [255,0,28,0, 1,0,0,0, 0,0,0,92, 5,0,11,7]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk
    print(Block2)
   
   
   
    print("AES AesDecrypt 2 - Cust")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    #print 'rk', Rk
    print(Block1)


    #################


    print("AES AesEncrypt 3")

    Rk = flatten([[0,0,0,0]]*(roundkey_index/4))
    Nr = 10
    Block1 = [255,0,28,15, 199,0,254,45, 0,89,0,92, 52,130,171,78]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk
    print(Block2)
   
   
   
    print("AES AesDecrypt 3")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    #print 'rk', Rk
    print(Block1)    



    print("AES AesEncrypt 3 - Cust")

    Rk = flatten([[78,15,93,2]]*(roundkey_index/4))
    Nr = 10
    Block1 = [255,0,28,15, 199,0,254,45, 0,89,0,92, 52,130,171,78]
    Block2 = AesEncrypt(Rk,Nr,Block1,verbose)
    #print 'rk', Rk    
    print(Block2)
   
   
   
    print("AES AesDecrypt 3 - Cust")
    Block1 = AesDecrypt(Rk,Nr,Block2,verbose)
    #print 'rk', Rk
    print(Block1)  

